/**
	This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.biofoco.p2p.bootstrap;

import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.biofoco.p2p.config.PeerConfigurationException;
import br.biofoco.p2p.peer.PeerNode;
import br.biofoco.p2p.peer.PeerNodeFactory;

import com.google.inject.Inject;


public class PeerApp {

	private static final Logger LOGGER = LoggerFactory.getLogger(PeerApp.class);
	private volatile boolean started = false;
	private final PeerNodeFactory peerNodeFactory;
	private PeerNode peerNode;
	private final CopyOnWriteArrayList<PeerNodeListener> listeners = new CopyOnWriteArrayList<PeerNodeListener>();
	
	private static final ExecutorService executor = Executors.newSingleThreadExecutor();
	
	@Inject
	public PeerApp(PeerNodeFactory factory) {
		this.peerNodeFactory = factory;

	}	

	public void initPeerInstance() throws IOException, PeerConfigurationException {		
		LOGGER.debug("Initializing peer instance ...");		
		peerNode = peerNodeFactory.getPeerInstance(true, true);	
		
		if(System.getProperty("schedule").equalsIgnoreCase("WQ")){
			peerNode.getMessenger().register(new BlastServer());
			LOGGER.debug("Initialized peer instance with ***** WQ schedule *********...");
		}
		else{
			peerNode.getMessenger().register(new TaskTracker());
			LOGGER.debug("Initialized peer instance with  *********** WQR ************ schedule...");
		}
		
		peerNode.start();		
	}		

	public void start() throws PeerConfigurationException, IOException {
		
		executor.submit(new Callable<Object>(){
			@Override
			public Object call() throws Exception {
				if (started)
					throw new IllegalStateException("Peer is already started");		
				initPeerInstance();		
				started = true;
				
				for (PeerNodeListener listener : listeners) 
					listener.onReady(peerNode);
				return null;
			}			
		});
	}

	public void addListener(PeerNodeListener listener) {
		this.listeners.add(listener);		
	}

	public PeerNode getPeerNode() {
		return peerNode;
	}
}
